#include "View.h"
#include "lang/Math.h"
using namespace yzrilyzr_lang;
namespace yzrilyzr_simplecanvas{
	View::View(){
		flags.add(FLAG_ENABLED);
	}
	int32_t View::getDefaultSize(int32_t size, MeasureSpec & measureSpec){
		int32_t result=size;
		switch(measureSpec.mode){
			case MeasureSpec::UNSPECIFIED:
				result=size;
				break;
			case MeasureSpec::AT_MOST:
			case MeasureSpec::EXACTLY:
				result=measureSpec.size;
				break;
		}
		return result;
	}
	int32_t View::px(int32_t dip){
		return dip * 3;
	}

#define SHOW_VIEW_BOUNDS
	void View::draw(SkCanvas & canvas){
		onDrawBackground(canvas);
		onDraw(canvas);
		dispatchDraw(canvas);
		onDrawForeground(canvas);
		flags.remove(PFLAG_INVALIDATED);
	#ifdef SHOW_VIEW_BOUNDS
		SkPaint paint;
		paint.setColor(SK_ColorRED);
		paint.setStyle(SkPaint::Style::kStroke_Style);
		paint.setStrokeWidth(3);
		SkRect rect;
		rect.setLTRB(edgeDistance.left, edgeDistance.top, edgeDistance.right, edgeDistance.bottom);
		canvas.drawRect(rect, paint);
	#endif //SHOW_VIEW_BOUNDS
	}
	void View::onDrawBackground(SkCanvas & canvas){
		if(background != nullptr){
			background->setBounds(0, 0, measuredWidth, measuredHeight);
			background->draw(canvas);
		}
	}
	void View::onDrawForeground(SkCanvas & canvas){
		if(foreground != nullptr){
			foreground->setBounds(0, 0, measuredWidth, measuredHeight);
			foreground->draw(canvas);
		}
	}

	void View::setBackground(std::shared_ptr<Drawable> v){
		background=v;
		invalidate();
	}
	void View::setForeground(std::shared_ptr<Drawable> v){
		foreground=v;
		invalidate();
	}

	bool View::dispatchDraw(SkCanvas & canvas){
		return false;
	}
	bool View::dispatchEvent(const UIEvent * event){
		return false;
	}
	void View::requestLayout(){
		flags.add(PFLAG_INVALIDATED | PFLAG_FORCE_LAYOUT);
		if(parent != nullptr)parent->requestLayout();
	}
	void View::layout(Rect & rect){
		Rect old=edgeDistance;
		edgeDistance=rect;
		bool changed=old == rect;
		onLayout(changed, old, rect);
		flags.remove(PFLAG_FORCE_LAYOUT);
	}
	void View::invalidate(){
		flags.add(PFLAG_INVALIDATED);
	}
	void View::measure(MeasureSpec & widthMeasureSpec, MeasureSpec & heightMeasureSpec){
		onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	void View::setMeasuredDimension(int32_t measuredWidth, int32_t measuredHeight){
		this->measuredWidth=measuredWidth;
		this->measuredHeight=measuredHeight;
	}
	void View::onDraw(SkCanvas & canvas){}
	void View::onLayout(bool changed, Rect & oldRect, Rect & newRect){}
	void View::onMeasure(MeasureSpec & widthMeasureSpec, MeasureSpec & heightMeasureSpec){
		setMeasuredDimension(getDefaultSize(minWidth, widthMeasureSpec),
							 getDefaultSize(minHeight, heightMeasureSpec));
	}
	void View::setPadding(Rect & rect){
		Rect old=rect;
		padding=rect;
		if(old != rect){
			requestLayout();
		}
	}
	void View::setMargin(Rect & rect){
		Rect old=rect;
		margin=rect;
		if(old != rect){
			requestLayout();
		}
	}
	std::shared_ptr<View> View::getParent(){
		return parent;
	}
	int View::getFinalVisibility(){
		int vi=visibility;
		View * v=this;
		while((v=v->getParent().get()) != nullptr){
			vi=Math::max(vi, v->getVisibility());
		}
		return vi;
	}
	int View::getVisibility(){
		return visibility;
	}
	void View::setEnabled(bool enable){
		if(enable == isEnabled())return;
		if(enable)flags.add(FLAG_ENABLED);
		else flags.remove(FLAG_ENABLED);
	}
	bool View::isEnabled(){
		return flags.has(FLAG_ENABLED);
	}
	Rect & View::getPadding(){
		return padding;
	}
	Rect & View::getMargin(){
		return margin;
	}
}